![]() | |
|
|
|
To access the contents, click the chapter and section titles.
Bug Proofing Visual Basic: A Guide to Error Handling and Prevention
Encapsulate with ControlsActiveX controls are a lot like classes. Both provide public methods, events, and property procedures to interact with the outside program. In many ways, a class is simply a control with no visible interface. Even the simplest Visual Basic program uses controls, so every Visual Basic programmer is familiar with them. While some programmers may not have mastered classes and object-oriented programming, they all know how to use controls. Take advantage of that preexisting experience by building ActiveX controls to encapsulate behavior. Controls have the advantage that you can distribute them in binary form. That means you can sometimes upgrade a control without recompiling an application. As long as you do not change the controls public interface, you can upgrade it quickly and easily without rebuilding the rest of the application. You can also allow other developers to use only the compiled OCX version of the control. That hides more detail from them so they are less likely to write code that relies on the controls internals. If they cannot see the source code, they cannot easily tie their code to the controls internal idiosyncrasies. Encapsulate with ModulesMany programmers overlook the fact that they can use modules to encapsulate data and functionality. A module can contain private variables, data structures, and routines that it needs but that are not needed by other parts of the program. To maximize encapsulation, as many of the modules details as possible should be private. For example, a work assignment program might keep a list of items sorted in priority order. The CreateJob subroutine creates a new job and adds it to the list. Subroutine GetNextJob fills in a user-defined data structure to describe the next job that must be worked. These subroutines could be placed inside a module. The list of jobs is stored using variables private to that module. All the rest of the program sees are the CreateJob and GetNextJob subroutines. The complexity of the job list is hidden from the main program. The jobs could be stored in an array, linked list, priority queue, tree, or some other data structure. Encapsulating the details of the job list within the module makes it easier to think about the rest of the program. While you concentrate on other parts of the code, you can ignore the job list internals. Encapsulating the job list also prevents the rest of the program from relying on the particular implementation of the lists internals. If you later find a bug in the way the list is stored, you can fix it without breaking the rest of the program. Group related routines in the same module so they are easy to find. Do not include unrelated routines in a module. This decreases the encapsulation provided by the module because the unrelated routine can access the modules private data. One module should contain all of the routines related to one topic and nothing more. Encapsulate with SubroutinesIf you use the same code more than once, place it in a subroutine. By calling the routine, you can reuse the code without having to write several copies. A less-obvious benefit of subroutines is that you only need to debug, test, and maintain one copy of the code. If duplicate code is replaced with a subroutine, you do not need to worry about keeping the separate copies synchronized when you make changes. One opportunity for reducing code duplication that is often overlooked is in form management code. If you perform the same task for many forms, write a subroutine in a .BAS module to do it. Make the routine take the form it should manipulate as a parameter. For example, the following routines save and restore a forms size and position in the system registry.
Save the forms size and position.
Public Sub SaveFormPosition(frm As Form)
SaveSetting MyProgram, Layout, frm.Name & Left, frm.Left
SaveSetting MyProgram, Layout, frm.Name & Top, frm.Top
SaveSetting MyProgram, Layout, frm.Name & Width, frm.Width
SaveSetting MyProgram, Layout, frm.Name & Height, frm.Height
End Sub
Reload the forms size and position.
Public Sub LoadFormPosition(frm As Form)
Dim l As Single
Dim t As Single
Dim w As Single
Dim h As Single
Get the settings.
l = GetSetting(MyProgram, Layout, frm.Name & Left, _
Format$(frm.Left))
t = GetSetting(MyProgram, Layout, frm.Name & Top, _
Format$(frm.Top))
w = GetSetting(MyProgram, Layout, frm.Name & Width, _
Format$(frm.Width))
h = GetSetting(MyProgram, Layout, frm.Name & Height, _
Format$(frm.Height))
Size and position the form.
frm.Move l, t, w, h
End Sub
Instead of placing code to save and load these values in each form, you can make the forms invoke these subroutines. A form could use these routines to set and save its size and position when it is loaded and unloaded, as shown in the following code:
Private Sub Form_Load()
LoadFormPosition Me
End Sub
Private Sub Form_Unload(Cancel As Integer)
SaveFormPosition Me
End Sub
Encapsulate ErrorsWhen a routine fails during design, it should stop to alert developers to the problem so they can fix it. In the final compiled version, the program must continue running even if an unexpected error occurs. This can be very difficult for some programs. If an operation completes only partially, it may leave data in an ambiguous state from which it is hard to continue. To minimize this kind of problem, routines should encapsulate their errors. They should hide the effects of their errors from calling routines. When a routine fails, it should undo any changes it has made to global data structures. Then the calling routine can continue operating without needing to know how much the routine accomplished before it failed.
|
|
Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-1999 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permision of EarthWeb is prohibited.
|